package org.cosmact.designer.vxml.gefeditor.editor;

import java.io.IOException;
import java.util.EventObject;

import org.apache.log4j.Logger;
import org.cosmact.designer.vxml.gefeditor.editpart.VxmlEditorRootEditPart;
import org.cosmact.designer.vxml.gefeditor.editpart.palette.DocumentEditorPaletteFactory;
import org.cosmact.designer.vxml.gefeditor.layout.DocumentLayoutFactory;
import org.cosmact.designer.vxml.gefeditor.layout.IDocumentLayout;
import org.cosmact.designer.vxml.model.persistence.ModelPersistenceService;
import org.cosmact.designer.xml.transfer.IVxmlTransfer;
import org.cosmact.designer.xml.transfer.VxmlTransferFactory;
import org.cosmact.vxml.model.Document;
import org.cosmact.vxml.model.ModelFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.requests.CreationFactory;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;

/**
 * 
 * 
 *@author YeXiaowei 234aini@gmail.com
 * 
 */
public class VxmlGefEditor extends GraphicalEditorWithPalette {

    Logger logger = Logger.getLogger(VxmlGefEditor.class);

    private Document vxmlDocument = null;

    private static PaletteRoot PALETTE_ROOT;

    private IFile fileInput;

    public VxmlGefEditor() {
	setEditDomain(new DefaultEditDomain(this));
    }

    @Override
    protected PaletteRoot getPaletteRoot() {
	PALETTE_ROOT = DocumentEditorPaletteFactory.createPalette();
	return PALETTE_ROOT;
    }

    @Override
    protected void initializePaletteViewer() {
	super.initializePaletteViewer();
	getPaletteViewer().addDragSourceListener(
		new TemplateTransferDragSourceListener(getPaletteViewer()));
    }

    @Override
    protected void initializeGraphicalViewer() {
	super.initializePaletteViewer();
	getGraphicalViewer().setContents(getModel());
    }

    @Override
    public void doSave(IProgressMonitor monitor) {
	monitor.beginTask("Save to xmi file", 1);
	try {
	    ModelPersistenceService.getService().save(getModel(),
		    fetchLocationFromFileInput());
	} catch (IOException e) {
	    e.printStackTrace();
	}
	// Use this to make the isDirty() return true
	getCommandStack().markSaveLocation();

	monitor.done();
    }

    private String fetchLocationFromFileInput() {
	return fileInput.getLocationURI().toString();
    }

    public Document getModel() {
	return vxmlDocument;
    }

    public Document setVxmlDocument(Document document) {
	return this.vxmlDocument = document;
    }

    @Override
    protected void setInput(IEditorInput input) {
	superSetInput(input);
	try {
	    IFileEditorInput fileInput = (IFileEditorInput) input;
	    setVxmlDocument(createDocumentFromFile(fileInput.getFile()));
	} catch (CoreException e) {
	    logger.error(e);
	}

    }

    /**
     * Create document from cos file or vxml file
     * 
     * @param file
     * @return
     * @throws CoreException
     */
    private Document createDocumentFromFile(IFile file) throws CoreException {
	Document document = null;
	if (file.getFileExtension().equalsIgnoreCase(EFileName.VXML.getName())) {
	    IVxmlTransfer transfer = VxmlTransferFactory.INSTANCE
		    .getVxmlTransfer();
	    document = transfer.parseVxml(file.getContents());
	    document.setName(file.getName());

	    layoutDocument(document);
	} else if (file.getFileExtension().equalsIgnoreCase(
		EFileName.COS.getName())) {
	    try {
		document = ModelPersistenceService.getService().read(
			fetchLocationFromFileInput());
	    } catch (Exception e) {
		document = ModelFactory.eINSTANCE.createDocument();
	    }
	}
	return document;
    }

    /**
     * Give position to dialog.
     * 
     * @param document
     */
    private void layoutDocument(Document document) {
	IDocumentLayout layout = DocumentLayoutFactory.getLayout(document,
		IDocumentLayout.DEFAULT_LAYOUT);
	layout.layout();
    }

    protected void superSetInput(IEditorInput input) {
	super.setInput(input);
	if (getEditorInput() != null
		&& getEditorInput() instanceof IFileEditorInput) {
	    fileInput = ((IFileEditorInput) getEditorInput()).getFile();
	    setPartName(fileInput.getName());
	}
    }

    @Override
    protected void configureGraphicalViewer() {
	super.configureGraphicalViewer();
	ScrollingGraphicalViewer viewer = (ScrollingGraphicalViewer) getGraphicalViewer();

	VxmlEditorRootEditPart root = new VxmlEditorRootEditPart();
	viewer.setRootEditPart(root);
	viewer.setEditPartFactory(new GraphicalPartFactory());

	viewer.setKeyHandler(new GraphicalViewerKeyHandler(viewer));
	getGraphicalViewer().addDropTargetListener(
		createTransferDropTargetListener());
    }

    @Override
    public void commandStackChanged(EventObject event) {
	firePropertyChange(IEditorPart.PROP_DIRTY);
	super.commandStackChanged(event);
    }

    /*
     * (non-Javadoc)
     * 
     * @seeorg.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#
     * createPaletteViewerProvider()
     */
    protected PaletteViewerProvider createPaletteViewerProvider() {
	return new PaletteViewerProvider(getEditDomain()) {
	    @Override
	    protected void configurePaletteViewer(PaletteViewer viewer) {
		super.configurePaletteViewer(viewer);
		viewer
			.addDragSourceListener(new TemplateTransferDragSourceListener(
				viewer));
	    }
	};
    }

    /**
     * Create a transfer drop target listener. When using a
     * CombinedTemplateCreationEntry tool in the palette, this will enable model
     * element creation by dragging from the palette.
     * 
     * @see #createPaletteViewerProvider()
     */
    private TransferDropTargetListener createTransferDropTargetListener() {
	return new TemplateTransferDropTargetListener(getGraphicalViewer()) {
	    @Override
	    protected CreationFactory getFactory(Object template) {
		return new ModelCreationFactory((Class<?>) template);
	    }
	};
    }

}
